#include "gtest/include/gtest/gtest.h"
#include "../../src/common/message/ngmessage.h"
#include "../../src/common/message/ngmessagecoder.h"
#include "../../src/common/message/ngdefaultmessagecoder.h"

class COMMON_NGDefaultMessageCoderTest : public ::testing::Test
{
protected:
	void SetUp()
	{
		msgCoder = new NGDefaultMessageCoder();

		encodedStr1[0] = 0x87;
		encodedStr1[1] = 50;
		encodedStr1[2] = -11;
		encodedStr1[3] = 0xFF;
		encodedStr1[4] = 'n';
		encodedStr1[5] = 'g';
		encodedStr1[6] = 'i';
		encodedStr1[7] = 'n';
		encodedStr1[8] = 'e';
		encodedStr1[9] = ' ';
		encodedStr1[10] = 't';
		encodedStr1[11] = 'e';
		encodedStr1[12] = 's';
		encodedStr1[13] = 't';
		encodedStr1[14] = 0x91;
		encodedStr1[15] = '\0';

		encodedStr2[0] = 0x87;
		encodedStr2[1] = 2;
		encodedStr2[2] = -14;
		encodedStr2[3] = 0xFF;
		encodedStr2[4] = 'h';
		encodedStr2[5] = 'e';
		encodedStr2[6] = 'l';
		encodedStr2[7] = 'l';
		encodedStr2[8] = 'o';
		encodedStr2[9] = ',';
		encodedStr2[10] = ' ';
		encodedStr2[11] = 'w';
		encodedStr2[12] = 'o';
		encodedStr2[13] = 'r';
		encodedStr2[14] = 'l';
		encodedStr2[15] = 'd';
		encodedStr2[16] = '!';
		encodedStr2[17] = 0x91;
		encodedStr2[18] = '\0';

		strcpy(data1, "ngine test");
		strcpy(data2, "hello, world!");

		type1 = 50;
		type2 = 2;

		length1 = strlen(data1);
		length2 = strlen(data2);

		headerSize = 4;
		trailerSize = 1;
	}
	void TearDown()
	{
		delete msgCoder;
	}

	NGDefaultMessageCoder *msgCoder;
	char encodedStr1[16];
	char encodedStr2[19];
	char data1[11];
	char data2[14];
	BYTE type1;
	BYTE type2;
	WORD length1;
	WORD length2;
	int headerSize;
	int trailerSize;
};

// test getHeaderSize() and getTrailerSize()
TEST_F(COMMON_NGDefaultMessageCoderTest, GetHeaderAndTrailerSizeTest)
{
	// test header size
	ASSERT_EQ(headerSize, msgCoder->getHeaderSize());

	// test trailer size
	ASSERT_EQ(trailerSize, msgCoder->getTrailerSize());
}

// test getMessageLength()
TEST_F(COMMON_NGDefaultMessageCoderTest, GetMessageLengthTest)
{
	// extract header
	char header1[headerSize + 1];
	memset(header1, 0, headerSize + 1);
	memcpy(header1, encodedStr1, headerSize);

	// get message length from header
	WORD compareLength1 = msgCoder->getMessageLength(header1);

	// test
	ASSERT_EQ(length1, compareLength1);


	// extract header
	char header2[headerSize + 1];
	memset(header2, 0, headerSize + 1);
	memcpy(header2, encodedStr2, headerSize);

	// get message length from header
	WORD compareLength2 = msgCoder->getMessageLength(header2);

	// test
	ASSERT_EQ(length2, compareLength2);
}

// test extractData()
TEST_F(COMMON_NGDefaultMessageCoderTest, ExtractDataTest)
{
	// extract data
	char *compareData1 = msgCoder->extractData(encodedStr1, length1);

	// test
	ASSERT_STREQ(data1, compareData1);

	free(compareData1);


	//extract data
	char *compareData2 = msgCoder->extractData(encodedStr2, length2);

	// test
	ASSERT_STREQ(data2, compareData2);

	free(compareData2);
}

// test encode()
TEST_F(COMMON_NGDefaultMessageCoderTest, EncodeTest)
{
	// create msg to use for testing
	NGMessage *msg1 = new NGMessage();
	msg1->setType(type1);
	msg1->setData(data1);

	// encode message
	char *compareStr1 = msgCoder->encode(msg1);

	// compare
	ASSERT_STREQ(encodedStr1, compareStr1);

	delete msg1;
	free(compareStr1);


	// create msg to use for testing
	NGMessage *msg2 = new NGMessage();
	msg2->setType(type2);
	msg2->setData(data2);

	// encode message
	char *compareStr2 = msgCoder->encode(msg2);

	// compare
	ASSERT_STREQ(encodedStr2, compareStr2);

	delete msg2;
	free(compareStr2);
}

// test decode()
TEST_F(COMMON_NGDefaultMessageCoderTest, DecodeTest)
{
	// decode message
	NGMessage *msg1 = msgCoder->decode(encodedStr1, 500);

	// test type
	ASSERT_EQ(type1, msg1->getType());
	ASSERT_EQ(length1, msg1->getLength());
	ASSERT_STREQ(data1, msg1->getData());
	ASSERT_EQ(500, msg1->getSenderId());

	delete msg1;


	// decode message
	NGMessage *msg2 = msgCoder->decode(encodedStr2, 1);

	// test type
	ASSERT_EQ(type2, msg2->getType());
	ASSERT_EQ(length2, msg2->getLength());
	ASSERT_STREQ(data2, msg2->getData());
	ASSERT_EQ(1, msg2->getSenderId());

	delete msg2;
}
